#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<time.h>
#define Size 10
// 初始化
void InitBoard(char (*board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            board[i][j] = '-';
        }
    }
}
// 打印棋盘
void PrintBoard(char (*board)[Size])
{   printf("     ");
    for (int i = 0; i < Size; i++)
        {
            printf(" %4d", i+1);
        }
        printf("\n");
    for (int i = 0; i < Size; i++)
    {   printf("%4d ",i+1);
        for (int j = 0; j < Size; j++)
        {
            printf(" %4c", board[i][j]);
        
        }
        printf("\n");
      
        
    }
}
//合法下棋点
bool IsValidPlace (int row,int column)
{   
    if (row<0||row>=Size||column<0||column>=Size)
    {
        return false;
    }
    return true;
    
}
//下棋
bool Makemove(char (*board)[Size], int row, int column, char player)
{ // 非法位置
    if (row < 0 || row > Size - 1 || column > Size - 1 || column < 0)
    {
        printf("非法的位置！请重新输入！\n");
        return false;
    }
    if (board[row][column] != '-')
    {
        printf("这个位置已经有棋子了，请重新输入！\n");
        return false;
    }
    board[row][column] = player;
    return true;
}
//判胜
bool CheckIsWin(char(*Board)[Size],int row,int column,char player)
{
    int direction[4][2]=
    {
        {1,0},{1,1},{0,1},{-1,1}
    };
    //遍历4个方向，数棋子数量
    for(int i=0;i<4;i++)
    {
        int count=1;
        //下一颗棋子位置
        int dx=row+direction[i][0];
        int dy=column +direction[i][1];
        while (IsValidPlace(dx,dy)&&Board[dx][dy]==player)
        {
            count++;
            if(count>=5)
            {
                return true;
            }
            dx=dx+direction[i][0];
            dy=dy+direction[i][1];
        }
        dx=row-direction[i][0];
        dy=column-direction[i][1];
         while (IsValidPlace(dx,dy)==true&&Board[dx][dy]==player)
        {
            count++;
            if(count>=5)
            {
                return true;
            }
            dx=dx -direction[i][0];
            dy=dy -direction[i][1];
        }
       
    }
    return false;
}
// 判平
bool CheckIsDraw(char (*board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (board[i][j] == '-')
            {
                return false;
            }
        }
    }
    return true;
}
//预测下两步
bool MayWin(char(*Board)[Size],int row,int column,char player)
{
   int direction[4][2]=
    {
        {1,0},{1,1},{0,1},{-1,1}
    };
    //遍历4个方向，数棋子数量
    for(int i=0;i<4;i++)
    {
        int count=1;
        //下一颗棋子位置
        int dx=row+direction[i][0];
        int dy=column +direction[i][1];
        while (IsValidPlace(dx,dy)&&Board[dx][dy]==player)
        {
            count++;
            if(count>=4)
            {
                return true;
            }
            dx=dx+direction[i][0];
            dy=dy+direction[i][1];
        }
        dx=row-direction[i][0];
        dy=column-direction[i][1];
         while (IsValidPlace(dx,dy)==true&&Board[dx][dy]==player)
        {
            count++;
            if(count>=4)
            {
                return true;
            }
            dx=dx -direction[i][0];
            dy=dy -direction[i][1];
        }
       
    }
    return false; 
}
//AI下棋策略
bool AIMakeMove(char(*Board)[Size],char player,char ai,int playerRow,int playerColumn)
{
    //优先取胜
    for(int i=0;i<Size;i++)
    {
        for(int j=0;j < Size;j++)
        {
            if(Board[i][j]=='-')
            {
                Board[i][j] = ai;
                if(CheckIsWin(Board,i,j,ai)==true)
                {   
                    return true;
                }
                 Board[i][j] = '-';
            }
        }
    }
    //阻止2步
    int count=0;
    for(int i=0;i<Size;i++)
    {
        for(int j=0;j < Size;j++)
        {
            if(Board[i][j]=='-')
            {
                Board[i][j] = player;
                if(MayWin(Board,i,j,player)==true)
                {   
                    count++;
                    if(count==2)
                    {
                        Board[i][j]=ai;
                        return true;
                    }
                    
                }
                Board[i][j]='-';
            }
        }
    }
    //阻止一步获胜
     for(int i=0;i<Size;i++)
    {
        for(int j=0;j < Size;j++)
        {
            if(Board[i][j]=='-')
            {
                Board[i][j] = player;
                if(CheckIsWin(Board,i,j,player)==true)
                {   
                    Board[i][j]=ai;
                    return true;
                    
                }
                Board[i][j]='-';
            }
        }
    }
    //随机下在玩家周围
    int direction[8][2]=
    {
        {1,0},{-1,0},{0,-1},{0,1},{1,1},{-1,1},{1,-1},{-1,-1}

    };
    //随机数产生跟随机种子
    //随机种子不变，随机数不变
    //以当前世界作为随机种子
    while(1)
    {   srand(time(NULL));
        int i=rand()%8;
        int dx=playerRow+direction[i][0];
        int dy=playerColumn+direction[i][1];
        if(IsValidPlace(dx,dy)&&Board[dx][dy]=='-')
        {
            Board[dx][dy]=ai;

            return true;
        }
    }
    
}




int main()
{
     char board[Size][Size];
    InitBoard(board);
    char player = 'x';
    int row = 0, column = 0;
    while (1)
    {
        PrintBoard(board);
        
        if(player=='x')
        {
        printf("请|%c|下棋", player);

        // 阻塞形函数:让函数等待条件满足
        scanf("%d %d", &row, &column);
        if (Makemove(board, row-1, column-1, player) == false)
        {
            continue;
        }
        if (CheckIsWin(board,row-1,column-1, player) == true)
        {
            PrintBoard(board);
            printf("恭喜|%c|获胜", player);
            break;
        }
        if (CheckIsDraw(board) == true)
        {
            PrintBoard(board);
            printf("平局！\n");
            break;
        }
        }
        if(player=='o')
        {
            printf("电脑正在下棋\n");
        if (AIMakeMove(board, 'x','o',row-1, column-1) == false)
        {
            continue;
        }
        if (CheckIsWin(board,row-1,column-1, 'o') == true)
        {
            PrintBoard(board);
            printf("恭喜|%c|获胜", player);
            break;
        }
        if (CheckIsDraw(board) == true)
        {
            PrintBoard(board);
            printf("平局！\n");
            break;
        }
        }
        if (player == 'x')
        {
            player = 'o';
        }
        else if (player == 'o')
        {
            player = 'x';
        }
       
    }

    return 0;
}